extends Node3D
class_name GridMapBoardManager

@export var mesh_library: MeshLibrary
@export var grid_map: GridMap

const BOARD_WIDTH = 21
const BOARD_HEIGHT = 12
const TILE_SIZE = 2.0

enum TileType {
	NEUTRAL = 0,
	PLAYER = 1,
	ENEMY = 2,
	OBSTACLE = 3
}

var occupied_tiles = {}
var tile_hover_overlay: MeshInstance3D

signal tile_clicked(x: int, z: int)
signal tile_hovered(x: int, z: int)

func _ready():
	print("GridMapBoardManager _ready() called")
	
	# Add to group for easier finding
	add_to_group("board")
	
	# Try to find the GridMap child if not exported
	if not grid_map:
		grid_map = get_node_or_null("GridMap")
		print("Found GridMap child: ", grid_map != null)
	
	if not grid_map:
		print("Creating new GridMap")
		grid_map = GridMap.new()
		grid_map.name = "GridMap"
		add_child(grid_map)
	
	if mesh_library:
		grid_map.mesh_library = mesh_library
		print("Using exported mesh library")
	else:
		var library_path = "res://tiles/TileLibrary.tres"
		if ResourceLoader.exists(library_path):
			grid_map.mesh_library = load(library_path)
			print("Loaded TileLibrary.tres")
		else:
			print("Warning: TileLibrary.tres not found!")
	
	grid_map.cell_size = Vector3(TILE_SIZE, 0.2, TILE_SIZE)
	grid_map.cell_center_y = false
	
	create_hover_overlay()
	create_default_board()
	
	print("GridMapBoardManager ready - has signal 'tile_clicked': ", has_signal("tile_clicked"))

func create_hover_overlay():
	tile_hover_overlay = MeshInstance3D.new()
	var box_mesh = BoxMesh.new()
	box_mesh.size = Vector3(TILE_SIZE * 0.95, 0.02, TILE_SIZE * 0.95)
	tile_hover_overlay.mesh = box_mesh
	
	var hover_mat = StandardMaterial3D.new()
	hover_mat.albedo_color = Color(1.0, 1.0, 0.3, 0.5)
	hover_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
	hover_mat.emission_enabled = true
	hover_mat.emission = Color(1.0, 1.0, 0.3)
	hover_mat.emission_energy = 0.3
	tile_hover_overlay.set_surface_override_material(0, hover_mat)
	
	add_child(tile_hover_overlay)
	tile_hover_overlay.visible = false

func create_default_board():
	# Create a static body for mouse raycasting
	var static_body = StaticBody3D.new()
	static_body.name = "BoardCollision"
	add_child(static_body)
	
	# Add a large collision shape covering the entire board
	var collision_shape = CollisionShape3D.new()
	var box_shape = BoxShape3D.new()
	box_shape.size = Vector3(BOARD_WIDTH * TILE_SIZE, 0.5, BOARD_HEIGHT * TILE_SIZE)
	collision_shape.shape = box_shape
	collision_shape.position = Vector3(0, -0.1, 0)
	static_body.add_child(collision_shape)
	
	for x in range(BOARD_WIDTH):
		for z in range(BOARD_HEIGHT):
			var tile_type = TileType.NEUTRAL
			
			if z < 4:  # Player zone
				tile_type = TileType.PLAYER
			elif z >= BOARD_HEIGHT - 4:  # Enemy zone
				tile_type = TileType.ENEMY
			
			grid_map.set_cell_item(Vector3i(x - BOARD_WIDTH/2, 0, z - BOARD_HEIGHT/2), tile_type)

func load_level(level_data: Dictionary):
	grid_map.clear()
	
	if level_data.has("tiles"):
		for tile in level_data["tiles"]:
			var pos = Vector3i(tile.x, tile.y, tile.z)
			var type = tile.type
			grid_map.set_cell_item(pos, type)
	
	if level_data.has("obstacles"):
		for obstacle in level_data["obstacles"]:
			var pos = Vector3i(obstacle.x, 0, obstacle.z)
			grid_map.set_cell_item(pos, TileType.OBSTACLE)

func grid_to_world(grid_x: int, grid_z: int) -> Vector3:
	var grid_pos = Vector3i(grid_x - BOARD_WIDTH/2, 0, grid_z - BOARD_HEIGHT/2)
	return grid_map.map_to_local(grid_pos) + Vector3(0, 0.2, 0)

func world_to_grid(world_pos: Vector3) -> Vector2i:
	var grid_pos = grid_map.local_to_map(world_pos)
	return Vector2i(grid_pos.x + BOARD_WIDTH/2, grid_pos.z + BOARD_HEIGHT/2)

func get_tile_at_position(world_pos: Vector3) -> Vector2i:
	return world_to_grid(world_pos)

func get_tile_world_position(x: int, z: int) -> Vector3:
	return grid_to_world(x, z)

func get_tile_type(x: int, z: int) -> int:
	var grid_pos = Vector3i(x - BOARD_WIDTH/2, 0, z - BOARD_HEIGHT/2)
	return grid_map.get_cell_item(grid_pos)

func set_tile_type(x: int, z: int, type: TileType):
	var grid_pos = Vector3i(x - BOARD_WIDTH/2, 0, z - BOARD_HEIGHT/2)
	grid_map.set_cell_item(grid_pos, type)

func is_tile_occupied(x: int, z: int) -> bool:
	var key = str(x) + "," + str(z)
	return occupied_tiles.has(key)

func set_tile_occupied(x: int, z: int, occupied: bool):
	var key = str(x) + "," + str(z)
	if occupied:
		occupied_tiles[key] = true
	else:
		occupied_tiles.erase(key)

func is_walkable(x: int, z: int) -> bool:
	if x < 0 or x >= BOARD_WIDTH or z < 0 or z >= BOARD_HEIGHT:
		return false
	
	var tile_type = get_tile_type(x, z)
	return tile_type != TileType.OBSTACLE and not is_tile_occupied(x, z)

func is_player_zone(z: int) -> bool:
	return z < 4

func is_enemy_zone(z: int) -> bool:
	return z >= BOARD_HEIGHT - 4

func get_adjacent_tiles(x: int, z: int) -> Array:
	var adjacent = []
	var directions = [
		Vector2i(1, 0), Vector2i(-1, 0),
		Vector2i(0, 1), Vector2i(0, -1),
		Vector2i(1, 1), Vector2i(-1, -1),
		Vector2i(1, -1), Vector2i(-1, 1)
	]
	
	for dir in directions:
		var new_x = x + dir.x
		var new_z = z + dir.y
		if is_walkable(new_x, new_z):
			adjacent.append(Vector2i(new_x, new_z))
	
	return adjacent

func highlight_tile(x: int, z: int):
	if x >= 0 and x < BOARD_WIDTH and z >= 0 and z < BOARD_HEIGHT:
		var world_pos = grid_to_world(x, z)
		tile_hover_overlay.position = world_pos + Vector3(0, 0.1, 0)
		tile_hover_overlay.visible = true

func unhighlight_tile(x: int, z: int):
	tile_hover_overlay.visible = false

func _input(event):
	if event is InputEventMouseMotion:
		handle_mouse_hover()
	elif event.is_action_pressed("mouse_left"):
		handle_mouse_click()
	elif event.is_action_pressed("mouse_right"):
		handle_mouse_click()  # Same handler, UnitManager will check which button

func get_mouse_world_position(mouse_pos: Vector2) -> Vector3:
	var camera = get_viewport().get_camera_3d()
	if not camera:
		return Vector3.ZERO
		
	var from = camera.project_ray_origin(mouse_pos)
	var to = from + camera.project_ray_normal(mouse_pos) * 1000
	
	var space_state = camera.get_world_3d().direct_space_state
	var ray_query = PhysicsRayQueryParameters3D.create(from, to)
	ray_query.collision_mask = 1
	var result = space_state.intersect_ray(ray_query)
	
	if result:
		return result.position
	return Vector3.ZERO

func handle_mouse_hover():
	var mouse_pos = get_viewport().get_mouse_position()
	var world_pos = get_mouse_world_position(mouse_pos)
	
	if world_pos != Vector3.ZERO:
		var tile_pos = world_to_grid(world_pos)
		if tile_pos.x >= 0 and tile_pos.x < BOARD_WIDTH and tile_pos.y >= 0 and tile_pos.y < BOARD_HEIGHT:
			highlight_tile(tile_pos.x, tile_pos.y)
			emit_signal("tile_hovered", tile_pos.x, tile_pos.y)
		else:
			tile_hover_overlay.visible = false

func handle_mouse_click():
	var mouse_pos = get_viewport().get_mouse_position()
	var world_pos = get_mouse_world_position(mouse_pos)
	
	print("Mouse click - World pos: ", world_pos)
	
	if world_pos != Vector3.ZERO:
		var tile_pos = world_to_grid(world_pos)
		print("Tile clicked: ", tile_pos, " Is valid: ", tile_pos.x >= 0 and tile_pos.x < BOARD_WIDTH and tile_pos.y >= 0 and tile_pos.y < BOARD_HEIGHT)
		if tile_pos.x >= 0 and tile_pos.x < BOARD_WIDTH and tile_pos.y >= 0 and tile_pos.y < BOARD_HEIGHT:
			emit_signal("tile_clicked", tile_pos.x, tile_pos.y)
			print("Emitted tile_clicked signal: ", tile_pos.x, ", ", tile_pos.y)

func create_pattern(pattern_type: String):
	match pattern_type:
		"checkerboard":
			for x in range(BOARD_WIDTH):
				for z in range(BOARD_HEIGHT):
					if (x + z) % 2 == 0:
						set_tile_type(x, z, TileType.NEUTRAL)
					else:
						set_tile_type(x, z, TileType.PLAYER if z < BOARD_HEIGHT/2 else TileType.ENEMY)
		
		"lanes":
			for x in range(BOARD_WIDTH):
				for z in range(BOARD_HEIGHT):
					if x % 3 == 1:
						set_tile_type(x, z, TileType.OBSTACLE)
					else:
						set_tile_type(x, z, TileType.NEUTRAL)
		
		"arena":
			create_default_board()
			# Add obstacles in corners
			for i in range(3):
				for j in range(3):
					if i < 3 and j < 3:
						set_tile_type(i, j, TileType.OBSTACLE)
						set_tile_type(BOARD_WIDTH - 1 - i, j, TileType.OBSTACLE)
						set_tile_type(i, BOARD_HEIGHT - 1 - j, TileType.OBSTACLE)
						set_tile_type(BOARD_WIDTH - 1 - i, BOARD_HEIGHT - 1 - j, TileType.OBSTACLE)